package smartbooks.ui.util;

import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.sql.Blob;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Map;
import java.util.Map.Entry;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.imageio.ImageIO;
import javax.sql.rowset.serial.SerialBlob;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JTextField;

/**
 *
 * @author Ankit
 */
public class CommonFunctions implements CommonConstants {
    
    /**
     * This method is used to get the Blob datatype from the Icon datatype
     * @param icon
     * @return Blob
     * @throws IOException
     * @throws SQLException
     */
    public static Blob getBLOBImageFromIcon(Icon icon) throws IOException, SQLException {
        if(null==icon) {
            return null;
        }
        
        Image image = ((ImageIcon)icon).getImage();
        BufferedImage bImage = new BufferedImage(image.getWidth(null),image.getHeight(null),BufferedImage.TYPE_INT_RGB);
        Graphics bg = bImage.getGraphics();
        bg.drawImage(image,0,0,null);
        bg.dispose();
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        ImageIO.write(bImage,"jpeg",out);
        byte[] buf = out.toByteArray();
        // setup stream for blob  
        //ByteArrayInputStream inStream = new ByteArrayInputStream(buf);
        Blob b = new SerialBlob(buf);
        return b;
    }
    
    /**
     * This method is used to scale the image (increase/decrease dimension)
     * @param w
     * @param h
     * @param img
     * @return BufferedImage
     * @throws Exception
     */
    public static BufferedImage scaleImage(int w, int h, BufferedImage img) throws Exception {
        BufferedImage bi;
        bi = new BufferedImage(w, h, BufferedImage.TRANSLUCENT);
        Graphics2D g2d = (Graphics2D) bi.createGraphics();
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g2d.addRenderingHints(new RenderingHints(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY));
        g2d.drawImage(img, 0, 0, w, h, null);
        g2d.dispose();
        return bi;
    }
    
    /**
     * This method will return true if the email is valid otherwise false
     * @param email
     * @return
     */
    public static boolean validateEmail(String email) {
        if(null==email) {
            return false;
        }
        
        String EMAIL_PATTERN = "^[_A-Za-z0-9-\\+]+(\\.[_A-Za-z0-9-]+)*@[A-Za-z0-9-]+(\\.[A-Za-z0-9]+)*(\\.[A-Za-z]{2,})$";
        
        Pattern pattern = Pattern.compile(EMAIL_PATTERN);
        Matcher matcher = pattern.matcher(email);
        
        return matcher.matches();
    }
    
    /**
     * This method is for TextArea and shifts the focus forward/backward on TAB/SHIFT+TAB
     * @param evt 
     */
    public static void textboxTABPolicy(KeyEvent evt) {
        if(evt.getKeyCode() == KeyEvent.VK_TAB){
            if(evt.isShiftDown()) {
                evt.getComponent().transferFocusBackward();
            } else {
                evt.getComponent().transferFocus();
            }
            evt.consume();
        }
    }
    
    /**
     * This method is used to get the Key from a map by its value
     * @param <T>
     * @param <E>
     * @param map
     * @param value
     * @return Key of a map
     */
    public static <T, E> T getKeyByValue(Map<T, E> map, E value) {
        for (Entry<T, E> entry : map.entrySet()) {
            if (value.equals(entry.getValue())) {
                return entry.getKey();
            }
        }
        return null;
    }
    
    /**
     * This function will dispose the entire Parent (JFrame/JDialog) on which the Container is.
     * @param c
     */
    public static void dispose(Container c) {
        while(c.getParent()!=null) {
            c = c.getParent();
            
            if(c instanceof JFrame){
                ((JFrame)c).dispose();
                return;
            }
            
            if(c instanceof JDialog) {
                ((JDialog)c).dispose();
                return;
            }
        }
    }
    
    /**
     * This function will fetch the parent JFrame on which the container is.
     * @param c
     * @return parent JFrame
     */
    public static JFrame getParentJFrame(Container c) {
        while(c.getParent()!=null) {
            c = c.getParent();
            
            if(c instanceof JFrame){
                return (JFrame)c;
            }
        }
        
        return null;
    }
    
    /**
     * This method is used to add Float pattern to a TextField.
     * Calling this function from KeyTyped event of a TextField will allow users to enter only Float type values.
     */
    public static void addFloatPatternKeyTypedListener(KeyEvent evt) {
        JTextField field = (JTextField)evt.getSource();
        char c = evt.getKeyChar();
        if (!Character.isDigit(c) && c!='.') {
            evt.consume();
        }

        if(c=='.') {
            if(field.getText().contains(".")) {
                evt.consume();
            } else if(field.getText().length()==0) {
                evt.consume();
            }
        }
    }
    
    /**
     * This method is used to temporarily populate the state and city map.
     * This should actually be coming from the database table.
     */
    public static void populateStateCityMapping() {        
        ArrayList<String> default_cities = new ArrayList<String>();
        default_cities.add("[Enter city]");
        stateCityMapping.put("[Enter state]", default_cities);
        
        ArrayList<String> port_blair = new ArrayList<String>();
        port_blair.add("[Enter city]");
        port_blair.add("Port Blair");
        stateCityMapping.put("Andaman and Nicobar Islands", port_blair);
        
        ArrayList<String> andhra_pradesh = new ArrayList<String>();
        andhra_pradesh.add("[Enter city]");
        andhra_pradesh.add("Adilabad");
        andhra_pradesh.add("Adoni");
        andhra_pradesh.add("Amadalavalasa");
        andhra_pradesh.add("Amalapuram");
        stateCityMapping.put("Andhra Pradesh", andhra_pradesh);
        
        ArrayList<String> assam = new ArrayList<String>();
        assam.add("[Enter city]");
        assam.add("Dhekiajuli");
        assam.add("Dhubri");
        assam.add("Dibrugarh");
        assam.add("Digboi");
        assam.add("Diphu");
        stateCityMapping.put("Assam", assam);
        
        ArrayList<String> bihar = new ArrayList<String>();
        bihar.add("[Enter city]");
        bihar.add("Hilsa");
        bihar.add("Hisua");
        bihar.add("Islampur");
        stateCityMapping.put("Bihar", bihar);
        
        
        ArrayList<String> goa = new ArrayList<String>();
        goa.add("[Enter city]");
        goa.add("Curchorem Cacora");
        goa.add("Goa Velha");
        stateCityMapping.put("Goa", goa);
        
        ArrayList<String> gujarat = new ArrayList<String>();
        gujarat.add("[Enter city]");
        gujarat.add("Adalaj");
        gujarat.add("Adityana");
        gujarat.add("Ahmedabad");
        gujarat.add("Anand");
        stateCityMapping.put("Gujarat", gujarat);
        
        ArrayList<String> maharashtra = new ArrayList<String>();
        maharashtra.add("[Enter city]");
        maharashtra.add("Mumbai");
        maharashtra.add("Murtijapur");
        maharashtra.add("Nagpur");
        maharashtra.add("Nalasopara");
        stateCityMapping.put("Maharashtra", maharashtra);
    }
}